﻿#include "YDecoderTask.h"
#include <iostream>
using namespace std;

extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}

/// <summary>
/// 打开解码器
/// </summary>
bool YDecoderTask::Open(AVCodecParameters* para)
{
	if (!para)
	{
		LOGERROR("para is null!");
		return false;
	}
	unique_lock<mutex> lock(mux_);
	is_open_ = false;
	auto c = decoder_.Create(para->codec_id, false);
	if (!c)
	{
		LOGERROR("decode_.Create failed!");
		return false;
	}
	//复制视频参数
	avcodec_parameters_to_context(c, para);
	decoder_.setContext(c);
	if (!decoder_.Open())
	{
		LOGERROR("decode_.Open() failed!");
		return false;
	}
	LOGINFO("Open decode success!");
	is_open_ = true;
	return true;
}

//责任链处理函数
void YDecoderTask::Do(AVPacket* pkt)
{
	//qDebug() << "#" << flush;

	if (!pkt || pkt->stream_index != 0) //判断是否是视频
	{
		return;
	}
	qDebug() << "解封装 push..." << pkt->stream_index;
	pkt_list_.Push(pkt);
	if (block_size_ <= 0)return;
	while (!isExit_)
	{
		if (pkt_list_.Size() > block_size_)
		{
			MSleep(1);
			qDebug() << "缓冲区数据已满";
			continue;
		}
		break;
	}
}

AVFrame* YDecoderTask::GetFrame()
{
	unique_lock<mutex> lock(mux_);
	if (frame_cache_)
	{
		if (frames_.empty())return nullptr;
		auto f = frames_.front();
		frames_.pop_front();
		return f;
	}


	if (!need_view_ ||  !frame_ || !frame_->buf[0])return nullptr;
	auto f = av_frame_alloc();
	auto re = av_frame_ref(f, frame_);//引用加1
	if (re != 0)
	{
		av_frame_free(&f);
		decoder_.PrintError(re, "GetFrame");
		return nullptr;
	}
	need_view_ = false;
	return f;
}
//线程主函数
void YDecoderTask::Working()
{
	{
		unique_lock<mutex> lock(mux_);
		if (!frame_)
			frame_ = av_frame_alloc();
	}
	long long cur_pts = -1;//当前解码到的pts（以解码数据为准）
	while (!isExit_)
	{
		if (isPause()) //暂停
		{
			MSleep(1);
			continue;
		}


		//同步（这段代码加上后视频播放就不对了，这块有bug，音视频同步时间戳的问题），音视频同步需要转移到PlayerController.cpp中完成
		/*while (!isExit_)
		{
			if (syn_pts_ >= 0 && cur_pts > syn_pts_)
			{
				qDebug() << "一直在同步";
				MSleep(1);
				continue;
			}
			break;
		}*/

		auto pkt = pkt_list_.Pop();
		if (!pkt)
		{
			this_thread::sleep_for(1ms);
			continue;
		}
		qDebug() << "解码 pop..." << pkt->stream_index;

		//发送到解码线程
		bool re = decoder_.Send(pkt);
		av_packet_free(&pkt);
		if (!re)
		{
			this_thread::sleep_for(1ms);
			continue;
		}
		{
			unique_lock<mutex> lock(mux_);
			if (decoder_.Receive(frame_))
			{
				qDebug() << "@" << flush;
				need_view_ = true;
				cur_pts = frame_->pts;
				//转换成毫秒
				if (time_base_)
					cur_ms_ = av_rescale_q(frame_->pts, *time_base_,
						{ 1,1000 });;
			}

			if (frame_cache_)
			{
				auto f = av_frame_alloc();
				av_frame_ref(f, frame_);//引用计数加1
				frames_.push_back(f);
			}
		}
		this_thread::sleep_for(1ms);
	}
	{
		unique_lock<mutex> lock(mux_);
		if (frame_)
			av_frame_free(&frame_);
	}
}

void YDecoderTask::set_time_base(AVRational* time_base)
{
	if (!time_base)return;
	unique_lock<mutex> lock(mux_);
	if (time_base_)
		delete time_base_;
	time_base_ = new AVRational();
	time_base_->den = time_base->den;
	time_base_->num = time_base->num;
}

/// <summary>
/// 清理缓存
/// </summary>
void YDecoderTask::Clear()
{
	pkt_list_.Clear();
	unique_lock<mutex> lock(mux_);
	while (!frames_.empty())
	{
		av_frame_free(&frames_.front());
		frames_.pop_front();
	}
	cur_pts_ = -1;
	decoder_.Clear();
}

void YDecoderTask::Stop()
{
	YThread::Stop();
	pkt_list_.Clear();
	unique_lock<mutex> lock(mux_);
	decoder_.setContext(nullptr);
	is_open_ = false;
	if (time_base_)
		delete time_base_;
	time_base_ = nullptr;
	while (!frames_.empty())
	{
		av_frame_free(&frames_.front());
		frames_.pop_front();
	}
}

YDecoderTask::YDecoderTask()
{
}

YDecoderTask::~YDecoderTask()
{
}
